<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1"><!-- Begin Jekyll SEO tag v2.8.0 -->
<title>0063: Cairo VII – Draw and Save Images | gtkDcoding</title>
<meta name="generator" content="Jekyll v4.3.4" />
<meta property="og:title" content="0063: Cairo VII – Draw and Save Images" />
<meta name="author" content="Ron Tarrant" />
<meta property="og:locale" content="en_US" />
<meta name="description" content="GTK Tutorial on drawing and saving images with Cairo." />
<meta property="og:description" content="GTK Tutorial on drawing and saving images with Cairo." />
<link rel="canonical" href="http://localhost:4000/posts/0063-cairo-vii-draw-save-images.html" />
<meta property="og:url" content="http://localhost:4000/posts/0063-cairo-vii-draw-save-images.html" />
<meta property="og:site_name" content="gtkDcoding" />
<meta property="og:type" content="article" />
<meta property="article:published_time" content="2019-08-20T00:00:00-04:00" />
<meta name="twitter:card" content="summary" />
<meta property="twitter:title" content="0063: Cairo VII – Draw and Save Images" />
<script type="application/ld+json">
{"@context":"https://schema.org","@type":"BlogPosting","author":{"@type":"Person","name":"Ron Tarrant"},"dateModified":"2019-08-20T00:00:00-04:00","datePublished":"2019-08-20T00:00:00-04:00","description":"GTK Tutorial on drawing and saving images with Cairo.","headline":"0063: Cairo VII – Draw and Save Images","mainEntityOfPage":{"@type":"WebPage","@id":"http://localhost:4000/posts/0063-cairo-vii-draw-save-images.html"},"url":"http://localhost:4000/posts/0063-cairo-vii-draw-save-images.html"}</script>
<!-- End Jekyll SEO tag -->
<link rel="stylesheet" href="../assets/main.css">
  <link rel="stylesheet" href="../css/style.css" /><link type="application/atom+xml" rel="alternate" href="http://localhost:4000/feed.xml" title="gtkDcoding" /></head>
<body><header class="site-header" role="banner">

  <div class="wrapper"><a class="site-title" rel="author" href="../">gtkDcoding</a><nav class="site-nav">
        <input type="checkbox" id="nav-trigger" class="nav-trigger" />
        <label for="nav-trigger">
          <span class="menu-icon">
            <svg viewBox="0 0 18 15" width="18px" height="15px">
              <path d="M18,1.484c0,0.82-0.665,1.484-1.484,1.484H1.484C0.665,2.969,0,2.304,0,1.484l0,0C0,0.665,0.665,0,1.484,0 h15.032C17.335,0,18,0.665,18,1.484L18,1.484z M18,7.516C18,8.335,17.335,9,16.516,9H1.484C0.665,9,0,8.335,0,7.516l0,0 c0-0.82,0.665-1.484,1.484-1.484h15.032C17.335,6.031,18,6.696,18,7.516L18,7.516z M18,13.516C18,14.335,17.335,15,16.516,15H1.484 C0.665,15,0,14.335,0,13.516l0,0c0-0.82,0.665-1.483,1.484-1.483h15.032C17.335,12.031,18,12.695,18,13.516L18,13.516z"/>
            </svg>
          </span>
        </label>

        <div class="trigger"><a class="page-link" href="../about.html">About</a><a class="page-link" href="../index-reverse.html">Posts in Date Order</a><a class="page-link" href="../topics.html">Blog Posts by Topic</a></div>
      </nav></div>
</header>
<main class="page-content" aria-label="Content">
      <div class="wrapper">
        <article class="post h-entry" itemscope itemtype="http://schema.org/BlogPosting">
	<header class="post-header">
		<link rel="stylesheet" href="../css/font_size.css" />
		<link rel="stylesheet" href="../css/figure.css" />
		<link rel="stylesheet" href="../css/topics/cairo.css" />  <!-- sub in the tag/topic -->
		<link rel="stylesheet" href="../css/modal.css" />
		<link rel="stylesheet" href="../css/post.css" />
		<link rel="stylesheet" href="../css/mascot_effects.css" />

		
		
		<p class="post-meta">
		<time class="dt-published" datetime="2019-08-20T00:00:00-04:00" itemprop="datePublished">Tuesday, August 20, 2019
		</time>• by <span itemprop="author" itemscope itemtype="http://schema.org/Person"><span class="p-author h-card" itemprop="name">Ron Tarrant</span></span></p>
	</header>

	<div class="post-content e-content" itemprop="articleBody">
		<div class="skew-line"></div>
		<h1 id="0063-cairo-vii--draw-and-save-images">0063: Cairo VII – Draw and Save Images</h1>

<p>So, this time we’re going to draw some images and then save them.</p>

<p><em><strong>Warning</strong>: These images are</em> not <em>high art and may or may not cause harm to your artistic sensibilities. (You’ve now been officially cautioned.)</em></p>

<p>In fact, because all these images are just a rectangle with text overlaid, I’m not even going to go over how they’re drawn. I’ll just say this one thing…</p>

<p>If you want a draw operation to be on top of another—like text overlaid on a rectangle, for instance—foreground draw operations need to be done <em>after</em> background draw operations. You probably sorted that out on your own, but there it is anyway.</p>

<h2 id="saving-images--basic-procedure">Saving Images – Basic Procedure</h2>

<p>Every time we save an image, we carry out the same set of operations:</p>

<ul>
  <li>find the size of the <code class="language-plaintext highlighter-rouge">DrawingArea</code>,</li>
  <li>grab the full expanse of the <code class="language-plaintext highlighter-rouge">DrawingArea</code>’s <code class="language-plaintext highlighter-rouge">Surface</code> that we want to save and stuff it into a buffer,</li>
  <li>set up the save options and option values for the image (this is different for each format), and</li>
  <li>save the image.</li>
</ul>

<p>But since each has their own save options, we’ll look at each individually starting with…</p>

<h2 id="saving-a-jpeg">Saving a JPeg</h2>

<!-- 0, 1 -->
<!-- first occurrence of application and terminal screenshots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img0" src="../images/screenshots/018_cairo/cairo_20.png" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal0" class="modal">																	<!-- modal# -->
				<span class="close0">&times;</span>															<!-- close# -->
				<img class="modal-content" id="img00" />															<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal0");														// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img0");															// img#
			var modalImg = document.getElementById("img00");													// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close0")[0];											// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img1" src="../images/screenshots/018_cairo/cairo_20_term.png" alt="Current example terminal output" />		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal1" class="modal">																				<!-- modal# -->
				<span class="close1">&times;</span>																		<!-- close# -->
				<img class="modal-content" id="img11" />																		<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal1");																	// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img1");																		// img#
			var modalImg = document.getElementById("img11");																// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close1")[0];														// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																								<!-- ------------- filename (below) --------- -->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/018_cairo/cairo_20_draw_save_jpeg.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for first (1st) occurrence of application and terminal screenshots on a single page -->

<p>Here’s the initialization section:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">GtkAllocation</span> <span class="n">size</span><span class="p">;</span>
<span class="n">Pixbuf</span> <span class="n">pixbuf</span><span class="p">;</span>
<span class="nb">string</span><span class="p">[]</span> <span class="n">jpegOptions</span><span class="p">,</span> <span class="n">jpegOptionValues</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">xOffset</span> <span class="p">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">yOffset</span> <span class="p">=</span> <span class="mi">0</span><span class="p">;</span>
</code></pre></div></div>

<p>We used a <code class="language-plaintext highlighter-rouge">GtkAllocation</code> object before, the main purpose of which is to get the size allocated to a <code class="language-plaintext highlighter-rouge">Widget</code>—in this case, the <code class="language-plaintext highlighter-rouge">DrawingArea</code>—so we don’t have to guess.</p>

<p>The <code class="language-plaintext highlighter-rouge">Pixbuf</code> is the buffer we’re going to stuff the image into as we prepare to save and the rest are pretty obvious:</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">jpegOptions</code>: an array of save options,</li>
  <li><code class="language-plaintext highlighter-rouge">jpegOptionValues</code>: an array of values for each of the save options,</li>
  <li><code class="language-plaintext highlighter-rouge">xOrigin</code>, <code class="language-plaintext highlighter-rouge">yOrigin</code>: the offset from the top-left corner of the <code class="language-plaintext highlighter-rouge">DrawingArea</code>.</li>
</ul>

<p><em>Note: If <code class="language-plaintext highlighter-rouge">xOffset</code> and <code class="language-plaintext highlighter-rouge">yOffset</code> are non-zero, we won’t be saving the entire image.</em></p>

<p><em>Note 2: The last two arguments to the <code class="language-plaintext highlighter-rouge">getFromSurface()</code> call (see the <code class="language-plaintext highlighter-rouge">onDraw()</code> snippet below), if less than the width and height of the <code class="language-plaintext highlighter-rouge">Surface</code>, will also save less than the entire image. Taking these two notes together, I’m sure you arrived at the conclusion that you can save any rectangular area of the Surface you choose.</em></p>

<p>I haven’t bothered with width and height variables here because these examples all save the entire <code class="language-plaintext highlighter-rouge">DrawingArea</code> and so we use the <code class="language-plaintext highlighter-rouge">width</code> and <code class="language-plaintext highlighter-rouge">height</code> fields from the <code class="language-plaintext highlighter-rouge">GtkAllocation</code> as we’ll see in a moment.</p>

<p>The constructor is so mundane as to warrant skipping in this discussion… so we shall.</p>

<p>As for the callback, we’ll leave out the drawing bit and go right for the meat:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">bool</span> <span class="n">onDraw</span><span class="p">(</span><span class="n">Scoped</span><span class="p">!</span><span class="n">Context</span> <span class="n">context</span><span class="p">,</span> <span class="n">Widget</span> <span class="n">w</span><span class="p">)</span>
<span class="p">{</span>
	<span class="c1">// set up and draw a rectangle</span>
	<span class="c1">// (see code file)</span>

	<span class="c1">// set up and draw text</span>
	<span class="c1">// (see code file)</span>

	<span class="n">getAllocation</span><span class="p">(</span><span class="n">size</span><span class="p">);</span> <span class="c1">// grab the widget's size as allocated by its parent</span>
	<span class="n">pixbuf</span> <span class="p">=</span> <span class="n">getFromSurface</span><span class="p">(</span><span class="n">context</span><span class="p">.</span><span class="n">getTarget</span><span class="p">(),</span> <span class="n">xOffset</span><span class="p">,</span> <span class="n">yOffset</span><span class="p">,</span> <span class="n">size</span><span class="p">.</span><span class="n">width</span><span class="p">,</span> <span class="n">size</span><span class="p">.</span><span class="n">height</span><span class="p">);</span> <span class="c1">// the contents of the surface go into the buffer</span>

	<span class="c1">// prep and write JPEG file</span>
	<span class="n">jpegOptions</span> <span class="p">=</span> <span class="p">[</span><span class="s">"quality"</span><span class="p">];</span> 
	<span class="n">jpegOptionValues</span> <span class="p">=</span> <span class="p">[</span><span class="s">"100"</span><span class="p">];</span>

	<span class="k">if</span><span class="p">(</span><span class="n">pixbuf</span><span class="p">.</span><span class="n">savev</span><span class="p">(</span><span class="s">"./rectangle_hw.jpg"</span><span class="p">,</span> <span class="s">"jpeg"</span><span class="p">,</span> <span class="n">jpegOptions</span><span class="p">,</span> <span class="n">jpegOptionValues</span><span class="p">))</span>
	<span class="p">{</span>
		<span class="n">writeln</span><span class="p">(</span><span class="s">"JPEG was successfully saved."</span><span class="p">);</span>
		
	<span class="p">}</span>

	<span class="k">return</span><span class="p">(</span><span class="kc">true</span><span class="p">);</span>
	
<span class="p">}</span> <span class="c1">// onDraw()</span>
</code></pre></div></div>

<p>And here’s what’s happening:</p>

<ul>
  <li>get the size of the <code class="language-plaintext highlighter-rouge">DrawingArea</code> with <code class="language-plaintext highlighter-rouge">getAllocation(size)</code>,</li>
  <li>grab either the entire <code class="language-plaintext highlighter-rouge">Surface</code> or a subsurface (by supplying a non-zero offset and/or a width and height less than the <code class="language-plaintext highlighter-rouge">Surface</code>’s <code class="language-plaintext highlighter-rouge">width</code> and <code class="language-plaintext highlighter-rouge">height</code>) and stuff it into a buffer (that’s the <code class="language-plaintext highlighter-rouge">Pixbuf</code>),</li>
  <li>set up the <em>JPeg</em> save options and their values, and</li>
  <li>call <code class="language-plaintext highlighter-rouge">Pixbuf.savev()</code> to save the image.</li>
</ul>

<h3 id="save-options-for-jpeg">Save Options for JPeg</h3>

<ul>
  <li>“icc-profile” - the complete ICC profile encoded into base64 (which, you’ll note, I didn’t bother with)</li>
  <li>“quality” - 0 … 100</li>
  <li>“x-dpi” - dots per inch (reasonable values: 50 to 300)</li>
  <li>“y-dpi” - dots per inch (same as x-dpi: 50 to 300)</li>
</ul>

<p>And that’s all there is to it.</p>

<h2 id="saving-a-png">Saving a PNG</h2>

<!-- 2, 3 -->
<!-- second occurrence of application and terminal screenshots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img2" src="../images/screenshots/018_cairo/cairo_21.png" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal2" class="modal">																<!-- modal# -->
				<span class="close2">&times;</span>														<!-- close# -->
				<img class="modal-content" id="img22" />														<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal2");													// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img2");														// img#
			var modalImg = document.getElementById("img22");												// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close2")[0];										// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img3" src="../images/screenshots/018_cairo/cairo_21_term.png" alt="Current example terminal output" /> 		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal3" class="modal">																			<!-- modal# -->
				<span class="close3">&times;</span>																	<!-- close# -->
				<img class="modal-content" id="img33" />																	<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal3");																// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img3");																	// img#
			var modalImg = document.getElementById("img33");															// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close3")[0];													// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																							<!--------- filename (below) ------------>
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/018_cairo/cairo_21_draw_save_png.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for second (2nd) occurrence of application and terminal screenshots on a single page -->

<p>Since everything else is the same, let’s skip right to the part of the callback that does the saving:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// prep and write to a PNG</span>
<span class="n">pngOptions</span> <span class="p">=</span> <span class="p">[</span><span class="s">"x-dpi"</span><span class="p">,</span> <span class="s">"y-dpi"</span><span class="p">,</span> <span class="s">"compression"</span><span class="p">];</span>
<span class="n">pngOptionValues</span> <span class="p">=</span> <span class="p">[</span><span class="s">"150"</span><span class="p">,</span> <span class="s">"150"</span><span class="p">,</span> <span class="s">"1"</span><span class="p">];</span>
	
<span class="k">if</span><span class="p">(</span><span class="n">pixbuf</span><span class="p">.</span><span class="n">savev</span><span class="p">(</span><span class="s">"./rectangle_hw.png"</span><span class="p">,</span> <span class="s">"png"</span><span class="p">,</span> <span class="n">pngOptions</span><span class="p">,</span> <span class="n">pngOptionValues</span><span class="p">))</span>
<span class="p">{</span>
	<span class="n">writeln</span><span class="p">(</span><span class="s">"PNG was successfully saved."</span><span class="p">);</span>
	
<span class="p">}</span>
</code></pre></div></div>

<p>So the differences here (compared to our first example) are:</p>

<ul>
  <li>set up the PNG save options,</li>
  <li>the values for each, and</li>
  <li>save with the <code class="language-plaintext highlighter-rouge">.png</code> file extension.</li>
</ul>

<h3 id="save-options-for-png">Save Options for PNG</h3>

<ul>
  <li>“x-dpi”	dots per inch (reasonable range is 50 to 300)</li>
  <li>“y-dpi”	dots per inch (same as x-dpi: 50 to 300)</li>
  <li>“tEXt::key” - an ASCII string of length 1 – 79, UTF-8 encoded strings</li>
  <li>“compression” - 0 … 9</li>
  <li>“icc-profile”	- the complete ICC profile encoded into base64</li>
</ul>

<h2 id="saving-a-tiff">Saving a TIFF</h2>

<!-- 4, 5 -->
<!-- third occurrence of application and terminal screenshots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img4" src="../images/screenshots/018_cairo/cairo_22.png" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal4" class="modal">																<!-- modal# -->
				<span class="close4">&times;</span>														<!-- close# -->
				<img class="modal-content" id="img44" />														<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal4");													// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img4");														// img#
			var modalImg = document.getElementById("img44");												// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close4")[0];										// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img5" src="../images/screenshots/018_cairo/cairo_22_term.png" alt="Current example terminal output" /> 		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal5" class="modal">																			<!-- modal# -->
				<span class="close5">&times;</span>																	<!-- close# -->
				<img class="modal-content" id="img55" />																	<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal5");																// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img5");																	// img#
			var modalImg = document.getElementById("img55");															// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close5")[0];													// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																							<!---------- filename (below) ---------->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/018_cairo/cairo_22_draw_save_tiff.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for third (3rd) occurrence of application and terminal screenshots on a single page -->

<p>As with the others, just set up the options and save:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">tiffOptions</span> <span class="p">=</span> <span class="p">[</span><span class="s">"bits-per-sample"</span><span class="p">,</span> <span class="s">"compression"</span><span class="p">];</span>
<span class="n">tiffOptionValues</span> <span class="p">=</span> <span class="p">[</span><span class="s">"8"</span><span class="p">,</span> <span class="s">"1"</span><span class="p">];</span>
	
<span class="k">if</span><span class="p">(</span><span class="n">pixbuf</span><span class="p">.</span><span class="n">savev</span><span class="p">(</span><span class="s">"./rectangle_hw.tiff"</span><span class="p">,</span> <span class="s">"tiff"</span><span class="p">,</span> <span class="n">tiffOptions</span><span class="p">,</span> <span class="n">tiffOptionValues</span><span class="p">))</span>
<span class="p">{</span>
	<span class="n">writeln</span><span class="p">(</span><span class="s">"TIFF was successfully saved."</span><span class="p">);</span>
		
<span class="p">}</span>
</code></pre></div></div>

<h3 id="save-options-for-tiff">Save Options for TIFF</h3>

<ul>
  <li>“bits-per-sample”
    <ul>
      <li>“1” for saving bi-level CCITTFAX4 images</li>
      <li>“8” for saving 8-bits per sample</li>
    </ul>
  </li>
  <li>“compression”
    <ul>
      <li>“1” for no compression</li>
      <li>“2” for Huffman</li>
      <li>“5” for LZW</li>
      <li>“7” for JPEG</li>
      <li>“8” for DEFLATE (see the libtiff documentation and tiff.h for all supported codec values)</li>
    </ul>
  </li>
  <li>“icc-profile” - (zero-terminated string) containing a base64 encoded ICC color profile.</li>
</ul>

<h2 id="saving-a-bmp">Saving a BMP</h2>

<!-- 6, 7 -->
<!-- third occurrence of application and terminal screenshots on a single page -->
<div class="screenshot-frame">
	<div class="frame-header">
		Results of this example:
	</div>
	<div class="frame-screenshot">
		<figure>
			<img id="img6" src="../images/screenshots/018_cairo/cairo_23.png" alt="Current example output" />		<!-- img# -->
			
			<!-- Modal for screenshot -->
			<div id="modal6" class="modal">																<!-- modal# -->
				<span class="close6">&times;</span>														<!-- close# -->
				<img class="modal-content" id="img66" />														<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal6");													// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img6");														// img#
			var modalImg = document.getElementById("img66");												// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close6")[0];										// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>
			<figcaption>
			Current example output
			</figcaption>
		</figure>
	</div>

	<div class="frame-terminal">
		<figure class="right">
			<img id="img7" src="../images/screenshots/018_cairo/cairo_23_term.png" alt="Current example terminal output" /> 		<!-- img#, filename -->

			<!-- Modal for terminal shot -->
			<div id="modal7" class="modal">																			<!-- modal# -->
				<span class="close7">&times;</span>																	<!-- close# -->
				<img class="modal-content" id="img77" />																	<!-- img## -->
				<div id="caption"></div>
			</div>
			
			<script>
			// Get the modal
			var modal = document.getElementById("modal7");																// modal#
			
			// Get the image and insert it inside the modal - use its "alt" text as a caption
			var img = document.getElementById("img7");																	// img#
			var modalImg = document.getElementById("img77");															// img##
			var captionText = document.getElementById("caption");

			img.onclick = function()
			{
			  modal.style.display = "block";
			  modalImg.src = this.src;
			  captionText.innerHTML = this.alt;
			}
			
			// Get the <span> element that closes the modal
			var span = document.getElementsByClassName("close7")[0];													// close#
			
			// When the user clicks on <span> (x), close the modal
			span.onclick = function()
			{ 
				modal.style.display = "none";
			}
			</script>

			<figcaption>
				Current example terminal output (click for enlarged view)
			</figcaption>
		</figure>
	</div>

	<div class="frame-footer">																							<!---------- filename (below) ---------->
		The code file for this example is available <a href="https://github.com/rontarrant/gtkd_demos/blob/master/018_cairo/cairo_23_draw_save_bmp.d" target="_blank">here</a>.
	</div>
</div>
<!-- end of snippet for fourth (4th) occurrence of application and terminal screenshots on a single page -->

<p>Everything’s the same, but there are no listed options so you have to pass in two empty arrays like this:</p>

<div class="language-d highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">if</span><span class="p">(</span><span class="n">pixbuf</span><span class="p">.</span><span class="n">savev</span><span class="p">(</span><span class="s">"./rectangle_hw.bmp"</span><span class="p">,</span> <span class="s">"bmp"</span><span class="p">,</span> <span class="p">[],</span> <span class="p">[]))</span>
<span class="p">{</span>
	<span class="n">writeln</span><span class="p">(</span><span class="s">"BMP was successfully saved."</span><span class="p">);</span>
		
<span class="p">}</span>
</code></pre></div></div>

<h2 id="conclusion">Conclusion</h2>

<p>And that’s most of what there is to saving images using Cairo. Next time, we’ll start digging into animation.</p>

<div class="blog-nav">
	<div style="float: left;">
		<a href="./0062-cairo-vi-load-display-images.html">Previous: Cairo Load &amp; Display Images</a>
	</div>
	<div style="float: right;">
		<a href="./0064-cairo-vii-drawingarea-animation.html">Next: Cairo DrawingArea Animation</a>
	</div>
</div>
<p>
	<h3></h3>
<div class="inpage-frame">
	<a href="https://github.com/sponsors/rontarrant">
		<BR>
		<BR>
		<B>Is this article useful? Educational? Entertaining, perhaps?</B>
		<BR>
		<figure class="left">
			<img src="../images/favorite_32.png" alt="Sponsorship heart" style="width: 32px; height: 32px;">
		</figure>
		You're free to accept or decline this invitation to become our newest sponsor.
	</a>
</div>
	<h4 class="comment-blurb"><B>Comments? Questions? Observations?</B></h4>
	<p>
		Did we miss a tidbit of information that would make this post even more informative? Let's talk about it in the comments.
	</p>
	<script src="https://utteranc.es/client.js"
		repo="rontarrant"
		issue-term="pathname"
		theme="github-light"
		crossorigin="anonymous"
		async>
	</script>
	<ul>
		<li> come on over to the <a href="https://forum.dlang.org/">D Language Forum</a> and look for one of the <i>gtkDcoding</i> announcement posts, </li>
		<li> drop by <a href="https://forum.gtkd.org/">the <i>GtkD Forum</i></a>,</li>
		<li> follow the link below to email me, or</li>
		<li> go to the	<a href="https://www.facebook.com">gtkDcoding Facebook page.</a></li>
	</ul>
</p>
<p> You can also subscribe <a href="/feed.xml">via RSS</a> so you won't miss anything. Thank you very much for dropping by.</p>
<p>&copy; Copyright 2025 Ron Tarrant </p>
</div>

	<a class="u-url" href="./0063-cairo-vii-draw-save-images.html" hidden></a>
</article>

      </div>
    </main><footer class="site-footer h-card">
  <data class="u-url" href="/"></data>

  <div class="wrapper">

    <h2 class="footer-heading">gtkDcoding</h2>

    <div class="footer-col-wrapper">
      <div class="footer-col footer-col-1">
        <ul class="contact-list">
          <li class="p-name">Ron Tarrant</li><li><a class="u-email" href="mailto:gtkDcoding@gmail.com">gtkDcoding@gmail.com</a></li></ul>
      </div>

      <div class="footer-col footer-col-2"><ul class="social-media-list"><li><a href="https://github.com/rontarrant"><svg class="svg-icon"><use xlink:href="../assets/minima-social-icons.svg#github"></use></svg> <span class="username">rontarrant</span></a></li></ul>
</div>

      <div class="footer-col footer-col-3">
        <p>Simple examples of how to use GtkD to build GUI applications.</p>
      </div>
    </div>

  </div>

</footer>
</body>

</html>
